/** @jsxImportSource @emotion/react */
import * as React from "react";
import { storiesOf } from "@storybook/react";
import {DdMenu,  DdMenuItem} from "../DropdownMenu";
import {ToastContainer, useToast} from "../Toast";
import {MainMenuBar, PanelEnlargeCtx, useMMenuBarOcup} from "../MainMenuBar";
import {MenuDivider, MenuItem, MenuList} from "../Menu";
import {Button,  buttonReset} from "../Button";
import {
    IconActivity,
    IconArrowLeft,
    IconArrowRight, IconArrowUpRight,
    IconChevronDown, IconChevronUp,
    IconKey, IconMapPin, IconMoreHorizontal,
    IconMoreVertical,
    IconPackage,
    IconUser
} from "../Icons";
import {
    Collapse,
    CommitInput,
    Input,
    InputLine,
    Pager,
    TabPanel,
    Text,
    useCollapse,
    useTheme,
    VerticalMenu
} from "../../src";
import {css} from "@emotion/react";
import {TwoHalfFrame } from "../TwoHalfFrame";
import {  Global } from "@emotion/react";
import {TwoHalfRightPanel} from "../TwoHalfRightPanel";
import {IconButton, IconRefButton} from "../IconButton";
import {useContext} from "react";
import {PanInfo} from "framer-motion";
import {Vector2} from "@use-gesture/core/dist/declarations/src/types/utils";
import {a, useSpring, useSprings, animated} from "@react-spring/web";
import {useDrag} from "@use-gesture/react";
import { useControls } from 'leva';
import {CSSProperties} from "react";
import styles from './styles.module.css'
import {useMeasure} from "../Hooks/use-measure";
import {usePrevious} from "../Hooks/previous";
import {UnitList} from "./TwoHalfCarousel.stories";


//对半开的页面装配框架
export const MenuStories = storiesOf("TwoHalfFrame", module)
    .add("嵌套Page", () => {
        return <NestedPage> <PagerUnitList/> </NestedPage>;
    })
    .add("套Draggable", () => {
        return <NestedPage> <DraggableNest/> </NestedPage>;
    })
    .add("定做轮播Pager", () => {
        return <NestedPage> <PagerCommon/> </NestedPage>;
    })
   .add("Basic", () => {
      //页面路由器头上面的部分
      const [enlarge, setEnlarge] = React.useState(null);
      //上面这句和底下的<PanelEnlargeCtx.Provider  value={{ enlarge, setEnlarge }}>正常应该出现在页面路由器入口组件上的。
      const theme = useTheme();
      const toast = useToast();
      //第1层次的两半页面轮播台控制
      const [activecas, setActivecas] = React.useState(0);
      const [activeTab, setActiveTab] = React.useState( 0);
       const [cod, setCod] = React.useState<string|undefined>('vU2');
       const [repNo, setRepNo] = React.useState<string|undefined>('');
       const [show, setShow] = React.useState(false);
       const eos =useCollapse(show,false);
       //【修改】独立<LeftPanelChanging/>两个半边页面状态变量不能交叉！   //另外半边右边的 ；报错！useMemo里面不允许函数体当中再嵌套useState;
       const rightPanel = React.useMemo(() => {
            //不能放这里：  const [show, setShow] = React.useState(true);
           return  <LeftPanelChanging/>;
       }, []);
     //StoryBook内嵌的 iframe当中，问题！ 被插入div， 高度被裁减。
    return (
        <PanelEnlargeCtx.Provider  value={{ enlarge, setEnlarge,  setActivecas }}>

            <Global
                styles={{
                    html: {
                        overflowX: 'hidden',
                        [theme.mediaQueries.md]: {
                            backgroundAttachment: "fixed",
                            backgroundSize: "cover",
                        },
                        padding: 'unset',
                    },
                    body:{
                        padding: '0 !important',
                    }
                }}
            />
            <MainMenuBar  css={{
                justifyContent: "space-between",
                "@media print": {
                    display: 'none',
                }
            }}
            >
                <DdMenu label="菜单"  divStyle={ {
                        lineHeight: '1.0',
                    } as any }
                >
                    <DdMenuItem label="Undo2" />
                    <DdMenuItem label="Redo3" />
                    <DdMenuItem label="Cut" disabled />
                    <DdMenu label="Copy as">
                        <DdMenuItem label="Text" />
                        <DdMenuItem label="Video" />
                        <DdMenu label="Image">
                            <DdMenuItem label=".png" />
                            <DdMenuItem label="是电风扇"
                                        onClick={ (e) => {
                                            toast({title: "提交一个3链接"});
                                        } }
                            />
                            <DdMenuItem label=".svg" />
                            <DdMenuItem label=".gif" />
                        </DdMenu>
                        <DdMenuItem label="Audio" />
                    </DdMenu>
                    <DdMenu label="Share">
                        <DdMenuItem label="Mail" />
                        <DdMenuItem label="Instagram" />
                    </DdMenu>
                </DdMenu>
                <Button
                    size="xs"
                    intent="primary"
                    iconBefore={<IconArrowRight />}
                    onPress={() => {  }}
                >
                    搜索
                </Button>
                <Button
                    size="xs"
                    intent="primary"
                    iconBefore={
                        <img
                            css={{
                                marginRight: theme.spaces.sm,
                                width: "25px",
                                height: "25px"
                            }}
                            src={''} alt={''}
                            aria-hidden
                        />
                    }
                    onPress={() => { } }
                >
                待办
                </Button>
                    <Button
                        size="xs" noBind
                        intent="primary"
                        iconBefore={<IconKey />}
                    >
                        任务
                    </Button>
            </MainMenuBar>

            <TwoHalfFrame  rightPanel={rightPanel} >
                <div  style={ {
                    display: 'flex',
                    alignItems: 'center',
                    flexDirection: 'column',
                  }  }>
                    <h5>Floating UI Dropdo wn Menu三事大夫UI Dropdown Menu三事大安达完了了翁另外市543多夫</h5>

                <Text variant="h3"
                    className="ListItem__primary"
                    wrap={true}
                    css={{ display: "block", fontWeight: 500 }}
                >
                   Floating UI Dropdo wn Menu三事大安达<p/>完了了翁另外市543多夫
                </Text>
                    <InputLine label={`立刻变动编号:`}>
                        <Input type='text'  value={ repNo || ''}
                               readOnly={false}  onChange={e => setRepNo( e.currentTarget.value||undefined ) } />
                    </InputLine>
                <InputLine label={`单位内部编号:`}>
                    <CommitInput autoFocus={true}  value={ cod || ''}  onSave={txt => setCod(txt||undefined) } />
                </InputLine>
                <Button
                    variant="ghost"
                    intent="primary"
                    iconAfter={eos.show  ? <IconChevronUp /> : <IconChevronDown />}
                    {...eos.buttonProps}
                    css={{whiteSpace:'unset'}}
                >
                    {<Text variant="h5" css={{color: eos.show ? theme.colors.palette.red.base:undefined}}>测试Collapse刻下guai</Text>}
                </Button>
                <Collapse {...eos.collapseProps}  noAnimated={false}>
                    shemta弹出可看的..<p/>.玩法师的
                    <div css={{textAlign: 'right',padding:'0.2rem'}}>
                        <Button
                            variant="ghost"
                            intent="primary"
                            iconAfter={eos.show  ? <IconChevronUp /> : <IconChevronDown />}
                            {...eos.buttonProps}
                        >
                         确认收起
                        </Button>
                    </div>
                </Collapse>

                </div>
            </TwoHalfFrame>

            <ToastContainer />
        </PanelEnlargeCtx.Provider>
    );
  });


interface Props {
    children?: React.ReactNode;
}
/*
TwoHalfFrame左右两边必须独立，需要确保左边页面的编辑器修改导致render不应该立刻引起右边页面的立刻变动。
* */
const LeftPanelChanging: React.FC<Props> =
({
     ...props
 }) => {
    const theme = useTheme();
    const toast = useToast();
    const [show, setShow] = React.useState(true);
    return (
        <TwoHalfRightPanel
            title={  `关联的检验信息 wn Menu三事大安达`
            }
            back={
                <IconButton  noBind  icon={<IconArrowLeft />}
                             variant="ghost"
                             label="后退"
                             size="md"
                             css={{
                                 marginRight: theme.spaces.sm,
                                 [theme.mediaQueries.md]: {
                                     display: "none"
                                 }
                             }}
                />
            }
            menu={
                <VerticalMenu>
                    <DdMenuItem label="Ro">
                        SFSD  <IconMoreVertical />
                    </DdMenuItem>
                    <DdMenuItem label="奇怪了"/>
                    <DdMenuItem label="事发地" onClick={(e) => {
                        toast({
                            duration: 99500,
                            title: "Hello world",
                            subtitle: "Excepteur exercitation 停留 2500 ms.afas四惠大少时诵诗书所厦大沙东",
                            //position: "top-right"
                            intent: 'error',
                        });
                    }}> <IconMoreVertical />
                    </DdMenuItem>
                    <DdMenuItem label="事地"  >
                        <div   css={{
                            display: 'inline-flex',
                            flexDirection: 'column',
                            flexWrap: 'wrap',
                            alignItems: 'center',
                            maxWidth: '9rem',
                            lineHeight: '1.1',
                        }} >sdfadf闪电发货手动滑稽是动画都或多或少35胜多负少都会
                        </div>
                    </DdMenuItem>
                    <DdMenuItem disabled label="Rzdo"   onPress={(e) => {
                        console.log("外部的7c7sa习性-")
                    }}
                    >Cut<IconMoreVertical />
                    </DdMenuItem>
                    <DdMenu
                        label="Copy as">
                        <DdMenuItem label="Text"/>
                        <DdMenuItem label="Video"/>
                        <DdMenu label="Image">
                            <DdMenuItem label=".png"/>
                            <DdMenuItem label="风扇Show"
                                        onClick={(e) => {
                                            setShow(!show);
                                            toast({
                                                render: ({ onClose, id }) => {return "show修改了！";}
                                            });
                                        }}/>
                            <DdMenuItem label=".svg"/>
                            <DdMenuItem label=".gif"/>
                        </DdMenu>
                        <DdMenuItem label="Audio"/>
                    </DdMenu>
                    <DdMenu label="Share">
                        <DdMenuItem label="Mail"/>
                        <DdMenuItem label="Instagram"/>
                    </DdMenu>
                </VerticalMenu>
            }
        >
            <h3>ARIA Authoring Practices show当前是={show? '真':'假'}, Guide</h3>
            <div css={{ padding: "1rem" }}>

                <MenuList>
                    <MenuItem contentBefore={<IconPackage />}
                              onPress={async () => {
                                  await toast({title: "提交一个网页链接"});
                              } }
                    >
                        提交审核
                    </MenuItem>
                    <MenuDivider />
                    <MenuItem
                        contentBefore={<IconUser />}
                        onPress={() => alert("Hello 1")}
                    >
                        Drink coffee
                    </MenuItem>
                    <MenuItem contentBefore={<IconPackage />}>Eat pancakes</MenuItem>
                    <MenuDivider />
                    <MenuItem contentBefore={<IconMapPin />}>Make pizza</MenuItem>
                    <MenuItem contentBefore={<IconActivity />}>
                        Dance {show? '真':'假'} out
                    </MenuItem>
                    <MenuItem contentBefore={<IconArrowUpRight />}>
                        Anything you ask
                    </MenuItem>
                </MenuList>

            </div>

        </TwoHalfRightPanel>
    );
};


interface NestedPageProps {
    children?: React.ReactNode;
}
const NestedPage: React.FunctionComponent<NestedPageProps> = ({children} )=> {
    const [enlarge, setEnlarge] = React.useState(null);
    const theme = useTheme();
    const toast = useToast();
    //第1层次的两半页面轮播台控制
    const [activecas, setActivecas] = React.useState(0);
    const [activeTab, setActiveTab] = React.useState( 0);
    const rightPanel=(
        <TwoHalfRightPanel
            title={  `关联的检验信息 wn Menu三事大安达`
            }
            back={
                <IconButton  noBind  icon={<IconArrowLeft />}
                             variant="ghost"
                             label="后退"
                             size="md"
                             css={{
                                 marginRight: theme.spaces.sm,
                                 [theme.mediaQueries.md]: {
                                     display: "none"
                                 }
                             }}
                />
            }
            menu={
                <VerticalMenu>
                    <DdMenuItem label="Ro">
                        SFSD  <IconMoreVertical />
                    </DdMenuItem>
                </VerticalMenu>
            }
        >

            <h3>ARIA Authoring Practices Guide</h3>
            <div css={{ padding: "1rem" }}>
            </div>
            <a
                target="_blank"
                href="https://www.w3.org/WAI/ARIA/apg/patterns/menubutton/"
                rel="noreferrer"
            >
                Menu Button
            </a>
        </TwoHalfRightPanel>
    );

    return (
        <PanelEnlargeCtx.Provider  value={{ enlarge, setEnlarge,  setActivecas }}>

            <Global
                styles={{
                    html: {
                        overflowX: 'hidden',
                        [theme.mediaQueries.md]: {
                            backgroundAttachment: "fixed",
                            backgroundSize: "cover",
                        },
                        padding: 'unset',
                    },
                    body:{
                        padding: '0 !important',
                    }
                }}
            />
            <MainMenuBar  css={{
                justifyContent: "space-between",
                "@media print": {
                    display: 'none',
                }
            }}
            >
                <Button
                    size="xs"
                    intent="primary"
                    iconBefore={<IconArrowRight />}
                    onPress={() => {  }}
                >
                    搜索
                </Button>
                <Button
                    size="xs"
                    intent="primary"
                    iconBefore={
                        <img
                            css={{
                                marginRight: theme.spaces.sm,
                                width: "25px",
                                height: "25px"
                            }}
                            src={''} alt={''}
                            aria-hidden
                        />
                    }
                    onPress={() => { } }
                >
                    待办
                </Button>
                <Button
                    size="xs" noBind
                    intent="primary"
                    iconBefore={<IconKey />}
                >
                    任务
                </Button>
            </MainMenuBar>

            <TwoHalfFrame  rightPanel={rightPanel}
            >
                <div  style={ {
                    display: 'flex',
                    alignItems: 'center',
                }  }>
                    <h5>Floating UI Dropdo wn Menu三事大夫UI Dropdown Menu三事大安达完了了翁另外市543多夫</h5>
                </div>
                <h3>Floating UI Dropdo wn Menu三事大安达完了了翁另外市543多夫</h3>

                {children}

            </TwoHalfFrame>
            <ToastContainer />
        </PanelEnlargeCtx.Provider>
    );
}

interface UnitMainProps {
    children?: React.ReactNode;
}
//内部嵌入 第二层的 一个轮播台
const PagerUnitList: React.FunctionComponent<UnitMainProps> = props => {
    const [activeTab, setActiveTab] = React.useState(0);
    const { enlarge, setEnlarge,setActivecas,getActivecas} =useContext(PanelEnlargeCtx);
    function onChildCannotDrag2(e: Event, dragProps: PanInfo) {
        const { offset } = dragProps
        if (offset.x > 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
        } else if (offset.x < 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
        }
    }
    //返回true=脱离控制，交给下一层次的的Pager控制
    const onChildCannotDrag = React.useCallback(([x, y]:Vector2) => {
        if (x < 0 || x > 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
            return true;
        }
        return false;
    }, [setActivecas, getActivecas]);


    const ref = React.useRef()

    const [color, setColor] = React.useState('black')
    const toggleColor = () => setColor((c) => (c === 'black' ? '#ec625c' : 'black'))

    const [style, api] = useSpring(() => ({ scale: 1, x: 0, y: 0 }))
    const [styleOuter, apiOuter] = useSpring(() => ({ x: 0, y: 0 }))
    const [coords, set] = React.useState({ x: 0, y: 0 })

    const { boundToParent, gesture, ...options } = useControls({
        enabled: true,
        gesture: { options: ['offset', 'movement'] },
        axis: { options: [undefined, 'x', 'y', 'lock'] },
        filterTaps: false,
        boundToParent: false,
        rubberband: false,
        triggerAllEvents: true
    })

    const pointerOptions = useControls('pointer', { touch: false, capture: true, lock: false })

    const bindOuter = useDrag((state) =>{
        const {offset: [x, y] , active, movement: [mx,my], direction: [xDir,yDir] , cancel,
            swipe:[swpx,], last,  canceled,tap, event,intentional } = state;
        console.log("Outer拉动",state,"active",active,"canceled:",canceled,"intentional",intentional);
        event.stopPropagation()    //也加上看
        apiOuter.start({ x, y })
    } )

    // @ts-ignore
    const bind = useDrag(
        (state) => {
            //这里intentional感觉不准确，过滤掉太多了，舍弃掉intentional状态变量。
            const {offset: [x, y] , active, movement: [mx,my], direction: [xDir,yDir] , cancel,
                swipe:[swpx,], last,  canceled,tap, event,intentional } = state;
            event.stopPropagation()    //去掉看
            //   if (intentional) {
            // let [x, y] = state[gesture]
            // set({ x, y })
            //
            // if (pointerOptions.lock) {
            //     const dx = window.innerWidth / 2 - 40
            //     const dy = window.innerHeight / 2 - 40
            //     x = ((x + Math.sign(x) * dx) % window.innerWidth) - Math.sign(x) * dx
            //     y = ((y + Math.sign(y) * dy) % window.innerHeight) - Math.sign(y) * dy
            // }
            api.start({
                // scale: active ? 1.2 : 1,
                x,
                y,
                // immediate: pointerOptions.lock
            })
            //  }
        },
        {
        }
    )

    return (
        <a.div  {...bindOuter()}  className={styles.hover}  style={styleOuter}

        >
            <div>
                <div>
                    <a.div  {...bind()}  className={styles.drag}  style={style}

                    >
                        <div onClick={toggleColor} style={{ backgroundColor: color }}>
                            <span>bind</span>
                            <span>
                            x:{Math.round(coords.x)}, y:{Math.round(coords.y)}
                        </span>
                        </div>
                    </a.div>
                </div>
            </div>
        </a.div>
    )

    return (
        <Pager  lazyLoad={false}  noBind={false}
                value={activeTab}   onRequestChange={i => setActiveTab(i)}
                onNestDragEnd={onChildCannotDrag}
                css={{
                    height: '100%',
                }}
        >
            <TabPanel id="company"
                      css={{
                          // height: '100%',
                      }}
            >
              {'公司'}
            </TabPanel>
            <TabPanel id="person"
                      css={{
                          // height: '100%',
                      }}
            >
              {'个人'}
            </TabPanel>
        </Pager>
    );
}
//内部嵌入 第二层的 一个轮播台
const DraggableNest: React.FunctionComponent<UnitMainProps> = props => {
    const [activeTab, setActiveTab] = React.useState(0);
    const { enlarge, setEnlarge,setActivecas,getActivecas} =useContext(PanelEnlargeCtx);
    function onChildCannotDrag2(e: Event, dragProps: PanInfo) {
        const { offset } = dragProps
        if (offset.x > 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
        } else if (offset.x < 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
        }
    }
    //返回true=脱离控制，交给下一层次的的Pager控制
    const onChildCannotDrag = React.useCallback(([x, y]:Vector2) => {
        if (x < 0 || x > 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
            return true;
        }
        return false;
    }, [setActivecas, getActivecas]);


    const ref = React.useRef()

    const [color, setColor] = React.useState('black')
    const toggleColor = () => setColor((c) => (c === 'black' ? '#ec625c' : 'black'))

    const [style, api] = useSpring(() => ({ scale: 1, x: 0, y: 0 }))
    const [styleOuter, apiOuter] = useSpring(() => ({ x: 0, y: 0 }))
    const [coords, set] = React.useState({ x: 0, y: 0 })

    const { boundToParent, gesture, ...options } = useControls({
        enabled: true,
        gesture: { options: ['offset', 'movement'] },
        axis: { options: [undefined, 'x', 'y', 'lock'] },
        filterTaps: false,
        boundToParent: false,
        rubberband: false,
        triggerAllEvents: true
    })

    const pointerOptions = useControls('pointer', { touch: false, capture: true, lock: false })

    // @ts-ignore
    const bind = useDrag(
        (state) => {
            //这里intentional感觉不准确，过滤掉太多了，舍弃掉intentional状态变量。
            const {offset: [x, y] , active, movement: [mx,my], direction: [xDir,yDir] , cancel,
                swipe:[swpx,], last,  canceled,tap, event,intentional } = state;
            event.stopPropagation()    //去掉看
            //   if (intentional) {
            // let [x, y] = state[gesture]
            // set({ x, y })
            //
            // if (pointerOptions.lock) {
            //     const dx = window.innerWidth / 2 - 40
            //     const dy = window.innerHeight / 2 - 40
            //     x = ((x + Math.sign(x) * dx) % window.innerWidth) - Math.sign(x) * dx
            //     y = ((y + Math.sign(y) * dy) % window.innerHeight) - Math.sign(y) * dy
            // }
            api.start({
                // scale: active ? 1.2 : 1,
                x,
                y,
                // immediate: pointerOptions.lock
            })
            //  }
        },
        {
        }
    )

    return (
        <div>
            <a.div  {...bind()}  className={styles.drag}  style={style}

            >
                <div onClick={toggleColor} style={{ backgroundColor: color }}>
                    <span>bind</span>
                    <span>
                    x:{Math.round(coords.x)}, y:{Math.round(coords.y)}
                </span>
                </div>
            </a.div>
        </div>
    )
}
//专用Pager测试修改版本， 内部的Stack也是测试修改版本
const PagerCommon: React.FunctionComponent<UnitMainProps> = props => {
    const [activeTab, setActiveTab] = React.useState(0);
    const { enlarge, setEnlarge,setActivecas,getActivecas} =useContext(PanelEnlargeCtx);
    function onChildCannotDrag2(e: Event, dragProps: PanInfo) {
        const { offset } = dragProps
        if (offset.x > 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
        } else if (offset.x < 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
        }
    }
    //返回true=脱离控制，交给下一层次的的Pager控制
    const onChildCannotDrag = React.useCallback(([x, y]:Vector2) => {
        if (x < 0 || x > 0) {
            setActivecas(getActivecas!()===1? 0 : 1);
            return true;
        }
        return false;
    }, [setActivecas, getActivecas]);


    const ref = React.useRef()

    const [color, setColor] = React.useState('black')
    const toggleColor = () => setColor((c) => (c === 'black' ? '#ec625c' : 'black'))

    const [style, api] = useSpring(() => ({ scale: 1, x: 0, y: 0 }))
    const [styleOuter, apiOuter] = useSpring(() => ({ x: 0, y: 0 }))
    const [coords, set] = React.useState({ x: 0, y: 0 })


    // @ts-ignore
    const bind = useDrag(
        (state) => {
            //这里intentional感觉不准确，过滤掉太多了，舍弃掉intentional状态变量。
            const {offset: [x, y] , active, movement: [mx,my], direction: [xDir,yDir] , cancel,
                swipe:[swpx,], last,  canceled,tap, event,intentional } = state;
            event.stopPropagation()    //去掉看
            //   if (intentional) {
            // let [x, y] = state[gesture]
            // set({ x, y })
            //
            // if (pointerOptions.lock) {
            //     const dx = window.innerWidth / 2 - 40
            //     const dy = window.innerHeight / 2 - 40
            //     x = ((x + Math.sign(x) * dx) % window.innerWidth) - Math.sign(x) * dx
            //     y = ((y + Math.sign(y) * dy) % window.innerHeight) - Math.sign(y) * dy
            // }
            api.start({
                // scale: active ? 1.2 : 1,
                x,
                y,
                // immediate: pointerOptions.lock
            })
            //  }
        },
        {
        }
    )

    return (
        <CommonPager  lazyLoad={false}  noBind={false}
                value={activeTab}   onRequestChange={i => setActiveTab(i)}
                onNestDragEnd={onChildCannotDrag}
                css={{
                    height: '100%',
                }}
        >
            <TabPanel id="company"
                      css={{
                          // height: '100%',
                      }}
            >
                <UnitList add={'公司'}/>
            </TabPanel>
            <TabPanel id="person"
                      css={{
                          // height: '100%',
                      }}
            >
                <UnitList add={'个人'}/>
            </TabPanel>
        </CommonPager>
    );
}

export interface GesturePageProps  {
    id?: string | undefined;
    //代表是当前显示哪一个儿子; onRequestChange配合执行，上级组件决定最终 value：index 该显示的儿子序号。
    value: number;
    //回调触发：切换到哪一个儿子去了
    //【注意】onRequestChange 必须把 value 参数值进行修改，否则无法真的切换。支持 异步的 懒惰加载组件数据。
    onRequestChange: (value: number) => void;

    //允许很长儿子队列只需要加载一部分儿子。
    lazyLoad?: boolean;      //懒加载总开关: 允许某些儿子mount实际时间滞后。
    //允许部分加载机制： 依据suggestedIndex来回调设置应当同时给与加载的那些兄弟，不是都是拖延加载的做法;
    onSetLazy?: (suggestedIndex: number) => number[];
    /* 拉不动了： 转交给上一级的轮播台机会拉动 ；
       beyondX 拉拽X方向已经超限制了：=-1 表示X轴左边超出  =1 表示X轴右边超出。  beyondY 高度方向的超出。
    * */
    onNestDragEnd?: (direction: Vector2) => boolean;

    //不能使用这样 paneStyle?: SerializedStyles;定义； 没法注入 style:{};
    paneStyle?: CSSProperties | undefined;

    children: Array<React.ReactNode>;
    //children: Array<React.ReactNode | CallbackProps>;
    //style: 隐藏 在HTMLAttributes里面
    style?: CSSProperties | undefined;
    //要不要允许手势操作处理，允许拉拽？
    noBind?: boolean;
    //电脑屏为了确保search input cancel触发最好改triggerAllEvents: false,
    searchCancel?: boolean;
}

//向上级组件暴露的操作接口
export interface PagerHandles {
    focus(i?: number): void;
}

/*任意内容 轮播台 类似于 CarouselPage ；
文档例子：https://codesandbox.io/s/github/pmndrs/use-gesture/tree/main/demo/src/sandboxes/draggable-list
* */
export const CommonPager  = React.forwardRef(
    ( {
          children,
          id,
          value: index,
          onRequestChange,
          lazyLoad = false,
          onSetLazy,
          onNestDragEnd,
          style,
          paneStyle,
          noBind=false,
          searchCancel=false,
          ...other
      } : GesturePageProps,
      ref
    ) =>  {
        const indexRef = React.useRef(index)
        const containerRef = React.useRef(null);      //绑定 拉拽的第一层Div;
        const width= useMeasure(containerRef)?.width | 0;
        //已经加载的部分： 多个儿子，不一定都加载mount完毕; 轮播切换不会卸载。 [index]默认只能加载一个;
        const [loaded, setLoaded] = React.useState(
            () => new Set(onSetLazy ? onSetLazy(index) : [index])
        );
        //当前已经加载的儿子映射DOM;
        const childrenRefs = React.useRef<Map<number, HTMLDivElement | null>>(
            new Map()
        );
        const previousIndex = usePrevious(index);
        const shouldFocusRef = React.useRef<number | null>(index || null);

        React.useEffect(() => {
            if (typeof previousIndex === "number" && previousIndex !== index) {
                shouldFocusRef.current = index;
            } else {
                shouldFocusRef.current = null;
            }
        }, [previousIndex, index]);
        //直接定位滚到某个儿子吗？
        function focusByIndex(i: number) {
            const el = childrenRefs.current.get(i);
            if (el) {
                el.focus();
            }
        }
        // expose an imperative focus function which focuses the currently active index
        //上级组件可能使用本接口直接操作 focusByIndex切换到某一个儿子， 跳过轮播滑动:也是可能切换轮播台的。
        React.useImperativeHandle(ref, () => ({
            focus: (i?: number) => {
                focusByIndex(i || index);
            }
        }));

        const renderableChildren = children.filter(child => child !== null);
        const childCount = renderableChildren.length;

        function isValidNextIndex(index: number) {
            return index >= 0  && index <= (childCount - 1);
        }

        /** 跟踪设置应该加载的儿子;
         * We keep a set of indexes that should
         * be loaded for lazy loading.
         * @param index:, 应该加载的儿子
         */
        function addIndexToLoaded(index: number) {
            if(!isValidNextIndex(index))    return;
            let indexes: number | number[] = index;
            // allow the user to customize which indexes to load
            if (onSetLazy) {
                indexes = onSetLazy(index);
            }
            const indexesArray = Array.isArray(indexes) ? indexes : [indexes];
            const next = new Set(loaded);
            //重新洗牌 next= 旧的已经加载儿子们；
            indexesArray.forEach(i => {
                // don't set items which are already loaded or are invalid
                if (loaded.has(i) || !isValidNextIndex(index)) {
                    return;
                }
                next.add(i);
            });
            setLoaded(next);
        }

        const {touchScr, } = useMMenuBarOcup(false);

        const { boundToParent, gesture, ...options } = useControls({
            enabled: true,
            gesture: { options: ['offset', 'movement'] },
            axis: { options: [undefined, 'x', 'y', 'lock'] },
            filterTaps: true,
            boundToParent: false,
            rubberband: false,
            triggerAllEvents: false
        })
        //控制器弹出窗口：实时 修改参数配置。
        const pointerOptions = useControls('pointer', { touch: true,mouse: false, capture: false, lock: true })

        const [anmprops, api] = useSprings(childCount, i => ({
            x: i * width,
            scale: 1,
            display: 'block',
        }));

        /*配置困难：为了确保电脑模式下的search input的cancel X 按钮的点击可清除编辑框内容，底下修改成：
            pointer: { mouse: true },
        * */
        const bind = useDrag((state) => {
                const { active, movement: [mx,my], direction: [xDir,yDir] , cancel,
                                 swipe:[swpx,], last,  canceled,tap, event } = state;
                event.stopPropagation()       //去掉看
                //if(tap)   return;
                if (active && Math.abs(mx) > width / 5) {
                    let Old=indexRef.current;
                    let finalDir= xDir!==0? xDir : mx>0? 1 : -1;
                    if(xDir===0  && yDir!==0)   finalDir=0;      //允许水平方向滑动
                    if(finalDir!==0) {
                        let midval = indexRef.current + (xDir > 0 ? -1 : 1);
                        const objIndex = midval < 0 ? 0 : midval > childCount - 1 ? childCount - 1 : midval;
                        // console.log("拉动End Old",Old,"objIndex=",objIndex);
                        if (objIndex === Old) {
                            cancel();
                            onNestDragEnd && onNestDragEnd([finalDir, 0]);
                        } else {
                            //滑动未到位就该触发懒加载的准备机制。
                            addIndexToLoaded(objIndex);
                            indexRef.current = objIndex;
                            onRequestChange(objIndex);
                            cancel();
                        }
                    }
                    else  cancel();
                }
                api.start(i => {
                    if (i < indexRef.current - 1 || i > indexRef.current + 1) return { display: 'none' }
                    const x = (i - indexRef.current) * width + (active ? mx : 0)
                    const scale = active ? 1 - Math.abs(mx) / width / 2 : 1
                    return { x, scale, display: 'block' }
                })
            },
            {
                // ...options,
                // pointer: pointerOptions,
                swipe: {velocity: 0.1},
                filterTaps: true,
                pointer: {touch: true, mouse: false, lock: touchScr},    //嵌套Pager拉拽避免拉动父辈层和search input的cancel在电脑模式点击能清空的要求正好冲突了。
                triggerAllEvents: true,     //电脑屏为了确保serach input cancel触发最好改triggerAllEvents: false,
                //enabled: !noBind,
            });
        /* #可能配置参数：
             eventOptions: { passive: false },
             threshold:  [3, 3] ,
             delay: 1000,
             pointer: { keys: true},
        * */
        const bind7 = useDrag(
            (state) => {
                const { active, movement: [mx,my], direction: [xDir,yDir] , cancel,
                    swipe:[swpx,], last,  canceled,tap, event } = state;
                console.log("拉动End",state,"active",active,"号序",indexRef.current,"canceled:",canceled,"swpx",swpx);
                event.stopPropagation()       //去掉看
                if(tap)   return;
                if(!active && last && !canceled && (Math.abs(swpx)>0 || (Math.abs(mx)>=width*0.03 && Math.abs(mx)>Math.abs(my) ) ) ) {
                    let Old=indexRef.current;
                    let finalDir= xDir!==0? xDir : mx>0? 1 : -1;
                    if(xDir===0  && yDir!==0)   finalDir=0;      //允许水平方向滑动
                    if(finalDir!==0){
                        const idxNew= indexRef.current + (finalDir>0 ? -1 : 1);
                        const objIndex= (idxNew > childCount - 1)? (childCount - 1) : idxNew<0? 0 :idxNew;
                        // console.log("拉动End Old",Old,"objIndex=",objIndex);
                        if(objIndex===Old){
                            cancel();
                            onNestDragEnd && onNestDragEnd([finalDir,0]);
                        }
                        else {
                            //滑动未到位就该触发懒加载的准备机制。
                            addIndexToLoaded(objIndex);
                            indexRef.current = objIndex;
                            onRequestChange(objIndex);
                            cancel();
                        }
                    }
                }
                api.start(i => {
                    if (i < indexRef.current - 1 || i > indexRef.current + 1) return { display: 'none' }
                    const x = (i - indexRef.current) * width + (active ? mx : 0)
                    const scale = active ? 1 - Math.abs(mx) / width / 2 : 1
                    return { x, scale, display: 'block' }
                });
            },
            {
                swipe: {velocity: 0.1},
                filterTaps: true,
                //手机触摸要pointerMouse=true;电脑却没法用！；
                enabled: !noBind,
            }
        )

        //visibility:hidden替换display:none, 组件状态被轮播Tabs切换以后均能保留;

        React.useEffect(() => {
            loaded.add(index);
            indexRef.current=index;
            api.start(i => {
                if (i < indexRef.current - 1 || i > indexRef.current + 1)
                    return { display: 'none' }
                const x = (i - indexRef.current) * width ;
                const scale =  1;
                return { x, scale, display: 'block' }
            })
        }, [index, width, api, loaded]);

        return (
            <div className="Pager"  key={id}
                 ref={containerRef}
                 style={{
                     position: 'relative',
                     overflow: 'hidden',
                     width: "100%",
                     height: "100%",
                     ...style,
                 }}
                 {...other}
            >
                {anmprops.map(({ x, display, scale }, i) =>{
                    const child= renderableChildren[i];
                    //传递给子页面： ref是一个动作函数(this) ？绑定时刻会执行ref函数: 非当前轮播儿子组件的直接"aria-hidden"隐藏?。
                    const sonprops = {
                        key: i,
                        tabIndex: index === i ? 0 : -1,
                        "aria-hidden": i !== index,
                    };
                    //代表已经允许mount加载了: load=true的儿子才能算正常DOM。load=false儿子说明未能够mount进来。允许很长队列只需要加载一部分儿子。
                    const load = !lazyLoad || index === i || loaded.has(i);

                    return(
                        <animated.div className='Pane'  {...bind()}
                                      key={i}
                                      style={{ display, x }}
                                      css={{
                                          position: 'absolute',
                                          width: "100%",
                                          height: "100%",
                                          touchAction: 'none',
                                      }}
                        >
                            <animated.div className='Page_pane'
                                          style={{
                                              scale,
                                              ...paneStyle
                                          }}
                                          css={{
                                              touchAction: 'none',
                                              //backgroundSize: 'cover',
                                              //backgroundRepeat: 'no-repeat',
                                              //backgroundPosition: 'center center',
                                              width: "100%",
                                              height: "100%",
                                              // boxShadow: `0 62.5px 125px -25px rgba(50, 50, 73, 0.5), 0 37.5px 75px -37.5px rgba(0, 0, 0, 0.6)`,
                                          }}
                                          {...sonprops}
                            >
                                {load && child}
                            </animated.div>
                        </animated.div>
                    ); })}
            </div>
        );
    }
);

